package cn.bonoon.kernel.descriptors.impl;

import java.lang.reflect.Field;
import java.util.ArrayList;
import java.util.List;

import cn.bonoon.kernel.annotations.condition.ConditionPrefix;
import cn.bonoon.kernel.descriptors.QueryDescriptor;
import cn.bonoon.kernel.descriptors.QueryPropertyAccessor;
import cn.bonoon.kernel.query.PageCondition;
import cn.bonoon.kernel.query.SearchCondition;

public final class QueryDescriptorImpl extends MappableClassDescriptor<QueryPropertyAccessor> implements QueryDescriptor{

	private final List<QueryPropertyAccessor> linkCache;
	private final String prefix;
	
	public QueryDescriptorImpl(Class<?> queryClass){
		super(queryClass);
		ConditionPrefix cp = queryClass.getAnnotation(ConditionPrefix.class);
		this.prefix = null == cp ? default_prefix : cp.value();
		this.linkCache = new ArrayList<QueryPropertyAccessor>();
	}
	
	@Override
	public QueryDescriptor initDescriptor() {
		super.initDescriptor();
		List<String> hasCached = new ArrayList<String>();
		for (QueryPropertyAccessor qpd : properties.values()) {
			String pn = qpd.getName();
			if(hasCached.contains(pn)) continue;
			hasCached.add(pn);
			linkCache.add(qpd);
			QueryPropertyAccessor last, next = qpd;
			while(next.isWith() 
					&& (last = properties.get(next.getNextProperty())) != null 
					&& !hasCached.contains(last.getName())){
				next = next.next(last);
				hasCached.add(last.getName());
			}
		}
		return this;
	}
	
	protected boolean filted(Class<?> cls){
		return super.filted(cls)
				|| PageCondition.class.equals(cls) 
				|| SearchCondition.class.equals(cls) ;
	}
	@Override
	protected QueryPropertyAccessorImpl parseProperty(Field field){
		return new QueryPropertyAccessorImpl(this, field);
	}
	
	public List<QueryPropertyAccessor> properties(){
		return linkCache;
	}

	public String getPrefix() {
		return prefix;
	}
}
